// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: taekwon

#include "coin2/exchange/okex_futures/api_order/native_rest_async_asio_subscriber.h"

#include <cstdlib>
#include <iostream>
#include <sstream>
#include <string>
#include <thread>

#include "coin2/base/log.h"

namespace coin2::exchange::okex_futures::api_order {

void OkexFuturesRestAsyncAsioSubscriber::QueryBalance(const std::string& native_symbol) {
  const auto& product = *symcache_->GetProductByNative(native_symbol);
  if (is_swap()) {
    auto http_context = rest_client()->QueryProductAccountInfo(product.native_symbol());
    http_context->handler =
        std::bind(&OkexFuturesRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
    http_driver_->PostAsyncContext(http_context);
  } else {
    auto query_symbol = product.base().native_currency() + "-" + product.quote().native_currency();
    auto http_context = rest_client()->QueryProductAccountInfo(query_symbol);
    http_context->handler =
        std::bind(&OkexFuturesRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
    http_driver_->PostAsyncContext(http_context);
  }
}

void OkexFuturesRestAsyncAsioSubscriber::QueryPosition(const std::string& native_symbol) {
  auto http_context = rest_client()->QueryProductPositionInfo(native_symbol);
  http_context->handler =
      std::bind(&OkexFuturesRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void OkexFuturesRestAsyncAsioSubscriber::QueryOpenOrders(const std::string& native_symbol) {
  auto http_context =
      rest_client()->QueryOrders(native_symbol, static_cast<int32_t>(OrderStatus::OPEN));
  http_context->handler =
      std::bind(&OkexFuturesRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void OkexFuturesRestAsyncAsioSubscriber::QueryDoneOrders(const std::string& native_symbol) {
  auto http_context =
      rest_client()->QueryOrders(native_symbol, static_cast<int32_t>(OrderStatus::DONE));
  http_context->handler =
      std::bind(&OkexFuturesRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void OkexFuturesRestAsyncAsioSubscriber::QueryFill(const std::string& native_symbol) {
  auto http_context = rest_client()->QueryFill(native_symbol);
  http_context->handler =
      std::bind(&OkexFuturesRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void OkexFuturesRestAsyncAsioSubscriber::QueryTransfer() {
  bool is_swap = rest_client()->is_swap();
  auto http_context = rest_client()->QueryTransfer(is_swap ? "ETH-USD-SWAP" : "ETH-USD", "");
  if (!http_context) return;
  http_context->handler =
      std::bind(&OkexFuturesRestAsyncAsioSubscriber::HandleQuery, this, std::placeholders::_1);
  http_driver_->PostAsyncContext(http_context);
}

void OkexFuturesRestAsyncAsioSubscriber::SubscribeAsync() {
  auto symbol_list = native_symbols();

  AddPeriodicTask(
      std::bind(&OkexFuturesRestAsyncAsioSubscriber::QueryBalance, this, std::placeholders::_1),
      config_.query_account_balance_period_sec(),
      "query_balance",
      symbol_list);

  AddPeriodicTask(
      std::bind(&OkexFuturesRestAsyncAsioSubscriber::QueryPosition, this, std::placeholders::_1),
      config_.query_account_position_period_sec(),
      "query_position",
      symbol_list);

  AddPeriodicTask(
      std::bind(&OkexFuturesRestAsyncAsioSubscriber::QueryOpenOrders, this, std::placeholders::_1),
      config_.query_open_orders_period_sec(),
      "query_open_orders",
      symbol_list);

  AddPeriodicTask(
      std::bind(&OkexFuturesRestAsyncAsioSubscriber::QueryDoneOrders, this, std::placeholders::_1),
      config_.query_cancel_orders_period_sec(),
      "query_done_orders",
      symbol_list);

  AddPeriodicTask(
      std::bind(&OkexFuturesRestAsyncAsioSubscriber::QueryFill, this, std::placeholders::_1),
      config_.query_fill_period_sec(),
      "query_fill",
      symbol_list);
}

}  // namespace coin2::exchange::okex_futures::api_order
